package com.kgis.map.cursor {
   import com.kgis.flexutil.collections.MapProvider;
   import com.kgis.map.Map;
   import com.kgis.map.common.enum.MapActionEnum;
   import com.kgis.map.events.FeatureEvent;

   import flash.display.Bitmap;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.filters.DropShadowFilter;
   import flash.ui.Mouse;

   import mx.managers.CursorManager;

   /**
    * 漫游状态为手型的鼠标光标
    */
   public class PanHandCursor extends Sprite {
      [Embed(source="/assets/hand.png")]
      private var HandUp:Class;

      [Embed(source="/assets/hand_down.png")]
      private var HandDown:Class;

      private var map:Map;
      private var enabled:Boolean = false;
      private var hand:Sprite;
      private var handup:Bitmap;
      private var handdown:Bitmap;

      private var callbacks:Array = [];

      public function PanHandCursor(map:Map) {
         this.map = map;

         mouseEnabled = false
         cacheAsBitmap = true;
         mouseChildren = false;

         hand = new Sprite();

         hand.alpha = 0.8;

         handup = new HandUp() as Bitmap;

         handdown = new HandDown() as Bitmap;

         hand.x -= hand.width / 2;
         hand.y -= hand.height / 2;
         hand.visible = false;
         addChild(hand);

         filters = [new DropShadowFilter(1, 45, 0, 1, 3, 3, .7, 2)];

         addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
      }

      public function onAddedToStage(event:Event):void {
         stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
         stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
         stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
         stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);

         map.addEventListener(MouseEvent.ROLL_OVER, enable);
         map.addEventListener(MouseEvent.ROLL_OUT, disable);
         map.addEventListener(FeatureEvent.FEATURE_OVER, featureOver);
         map.addEventListener(FeatureEvent.FEATURE_OUT, featureOut);
         map.addEventListener(FeatureEvent.FEATURE_SELECTBYBOX, featureSelectBox);
      }

      private function featureOver(ev:FeatureEvent):void {
         if (enabled && map.operateMode == MapActionEnum.MAP_PAN) {
            Mouse.show();
            callNextFrame(Mouse.show);
            if (hand.contains(handup)) {
               hand.removeChild(handup);
            }
         }

      }

      private function featureOut(ev:FeatureEvent):void {
         if (enabled && map.operateMode == MapActionEnum.MAP_PAN) {
            Mouse.hide();
            callNextFrame(Mouse.hide);
            if (hand.contains(handdown)) {
               hand.removeChild(handdown);
            }
            if (!hand.contains(handup)) {
               hand.addChild(handup);
            }
         }

      }

      private function featureSelectBox(ev:FeatureEvent):void {
         if (map.operateMode == MapActionEnum.MAP_PAN) {
            handUpVisiable();
            enabled = true;
         }

      }

      private function onRemovedFromStage(event:Event):void {
         stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
         stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
         stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
         stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave);

         map.removeEventListener(MouseEvent.ROLL_OVER, enable);
         map.removeEventListener(MouseEvent.ROLL_OUT, disable);
         map.addEventListener(FeatureEvent.FEATURE_SELECTBYBOX, featureSelectBox);
      }

      private function onMouseLeave(event:Event):void {
         if (enabled) {
            hand.visible = false;
         }
      }

      private function onMouseMove(event:MouseEvent):void {
         if (enabled && !hand.visible && map.operateMode == MapActionEnum.MAP_PAN) {
            hand.visible = true;
         }
         x = map.mouseX;
         y = map.mouseY;
      }

      private function onMouseUp(event:MouseEvent):void {
         if (enabled) {
            handUpVisiable();

         }
      }

      private function onMouseDown(event:MouseEvent):void {
         try {
            if (enabled) {
               handDownVisiable();
            }
         }
         catch (e:Error) {
         }
      }

      private function enable(event:Event = null):void {
         if (map.operateMode == MapActionEnum.MAP_PAN) {
            hand.visible = true;
            enabled = true;
            if (hand.contains(handdown) || hand.contains(handup)) {
               Mouse.hide();
               callNextFrame(Mouse.hide);
            }

         }

      }

      private function disable(event:Event = null):void {
         Mouse.show();
         CursorManager.removeAllCursors();
         callNextFrame(Mouse.show);
         hand.visible = false;
         enabled = false;
      }

      private function callNextFrame(callback:Function):void {
         if (!hasEventListener(Event.ENTER_FRAME)) {
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
         }
         callbacks.push(callback);
      }

      private function onEnterFrame(event:Event):void {
         while (callbacks.length > 0) {
            var callback:Function = callbacks.shift() as Function;
            callback();
         }
         removeEventListener(Event.ENTER_FRAME, onEnterFrame);
      }

      private function handUpVisiable():void {
         Mouse.hide();
         callNextFrame(Mouse.hide);
         if (hand.contains(handdown)) {
            hand.removeChild(handdown);
         }
         if (!hand.contains(handup)) {
            hand.addChild(handup);
         }
      }

      private function handDownVisiable():void {
         Mouse.hide();
         CursorManager.removeAllCursors();
         callNextFrame(Mouse.hide);
         if (hand.contains(handup)) {
            hand.removeChild(handup);
         }
         if (!hand.contains(handdown)) {
            hand.addChild(handdown);
         }
      }

   }
}